using UnityEngine;
using System.Collections;

public class Pawn : MonoBehaviour
{

    private float m_Speed = 10.0f;
    public float m_SpeedMidAir = 10.0f;
    public float m_SpeedGrounded = 5.0f;
    public float m_Mass = 10.0f;
    
    public float m_maximumUpwardsForce = 5.0f;

    private float m_CurrentRecoilForce = 0;
    private Vector3 m_RecoilDirection = Vector3.zero;

    private float m_CurrentHoverForce = 0;
    private Vector3 m_HoveDirection = Vector3.zero;

    public bool m_bDead = false;
    
    private bool m_bIsGravity = true;

    //collision with boxes
    public float pushPower = 25.0f;
    public float m_fDistanceForceBreakingFactor = 50f;

    public Vector3 m_MoveDirection = Vector3.zero;

    private Vector3 m_MoveVec = Vector3.zero;

    CharacterController Controller;
    GameObject[] m_RespawnPoints;
    GameObject m_CurrentActiveRespawn;


    void Start()
    {
        Controller = GetComponent<CharacterController>();

        //fill the array with respawnpoints
        m_RespawnPoints = GameObject.FindGameObjectsWithTag("Respawn");

        //Keep the first respawnpoint because it is the first spawnpoint active
        m_CurrentActiveRespawn = m_RespawnPoints[0];

    }

    // Update is called once per frame
    void Update()
    {
        //LATER WE NEED TO ROTATE THE ARMS AND WEAPONS

        if (Controller.isGrounded)
        {
            m_MoveDirection.y = 0;
            m_Speed = m_SpeedGrounded;
        }
        else
        {
            m_Speed = m_SpeedMidAir;
        }

        //Create vector to let our character move horizontal
        m_MoveDirection.x = transform.forward.x * Input.GetAxis("Horizontal") * m_Speed;

        if (m_bIsGravity)
        {
            // Calculate gravity
            m_MoveDirection.y -= m_Mass * ProjectHelper.m_Gravity * Time.deltaTime;
        }

        // Calculate the recoil if any
        Vector3 finalRecoil = m_RecoilDirection * m_CurrentRecoilForce ;

        //Calculate the hover
        Vector3 hoverForce = m_HoveDirection * m_CurrentHoverForce;

        // Calculate final moveVector
        m_MoveVec = m_MoveDirection + finalRecoil + hoverForce;

        // Put in some restrictions based on gameplay rules
        // clamp upwards force if above the maximum
        if (m_MoveVec.y > m_maximumUpwardsForce)
            m_MoveVec.y = m_maximumUpwardsForce;

        //Move the pawn
        Controller.Move(m_MoveVec * Time.deltaTime);

        //damp the recoil force
        m_CurrentRecoilForce = Mathf.Lerp(m_CurrentRecoilForce, 0f, 2.5f * Time.deltaTime);


        if (m_bDead)
        {
            //for lus to check wich respawnpoint is active
            for (int index = 0; index < m_RespawnPoints.Length; ++index)
            {
                //check wich one is active
                if (m_RespawnPoints[index].GetComponent<Respawn>().m_bActive)
                {

                        //place the controller on the position of the active Respawnpoint
                        transform.position = m_RespawnPoints[index].transform.position;
                }
            }

            //reset bool
            m_bDead = false;
        }
    }

    // Collision used to push objects
    void OnControllerColliderHit(ControllerColliderHit hit)
    {
        if (m_CurrentRecoilForce > 2f)
        {
            Rigidbody body = hit.collider.attachedRigidbody;

            //check if we received the actual body and if it can be moved
            if (body == null || body.isKinematic)
                return;

            //define the direction (2D)
            Vector3 pushDir = new Vector3(hit.moveDirection.x, 0, hit.moveDirection.z);

            //Finally pass the velocity so the object moves
            float power = pushPower * (m_CurrentRecoilForce / m_fDistanceForceBreakingFactor);
            body.velocity = pushDir * power;
            body.SetDensity(1.0f);

            m_CurrentRecoilForce = 0;
        }
    }

    public void GiveRecoil(float force, Vector3 direction)
    {
        m_CurrentRecoilForce = force;
        m_RecoilDirection = Vector3.Normalize(direction);
        //lock z-axis for depth
        m_RecoilDirection.z = 0;
    }

    public void SetBoolGravity(bool isGravity)
    {
        m_bIsGravity = isGravity;
    }

    public void SetHoverForce(float force, Vector3 direction)
    {
        m_CurrentHoverForce = force;
        m_HoveDirection = Vector3.Normalize(direction);
        //lock z-axis for depth
        m_HoveDirection.z = 0;
    }
}
